#ifndef VMEXEC_H
#define VMEXEC_H


#include <QtGlobal>

#include "VMValue.h"

namespace CuteVM {

    class ExecError; // forward
    class Instruction;
    class Machine;

    class ExecResult {
    private:
        int pc;
        Instruction & instr;
        Machine *vm;
    protected:
        ExecResult(Machine *vm, Instruction &instr);
    public:
        virtual bool isError() = 0;
        virtual ExecError & asError() = 0;
        virtual Value * getValue() = 0;

        int getPC() { return pc; }
        void setPC(int pc) { this->pc = pc; }
        Instruction & getInstruction() { return instr; }
        Machine * getMachine() { return vm; }
        void setMachine(Machine *vm) { this->vm = vm; }
    };


    class ExecError : public ExecResult {
    private:
        QString message;
    public:
        ExecError(Machine *vm, Instruction & instr, QString message) :  ExecResult(vm,instr), message(message)
        { }

        bool isError() {
            return true;
        }

        Value * getValue() { return NULL; }

        QString getMessage() { return message; }
        void setMessage(QString message) { this->message = message; }


        ExecError & asError() {
            return *this;
        }
    };

    class ExecSuccess : public ExecResult {
    private:
        ExecError noError;
        Value * value;
    public:
        ExecSuccess(Machine *vm, Instruction &instr);

        bool isError() {
            return false;
        }

        Value * getValue() { return value; }
        void setValue(Value * value) { this->value = value; }

        ExecError & asError() {
            qFatal("Not an error (please report)");
            return noError;
        }
    };

} // namespace CuteVM

#endif // VMEXEC_H
